package org.sam.swing.treetableImpl;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreePath;

import org.apache.commons.lang3.StringUtils;
import org.jdesktop.swingx.treetable.AbstractTreeTableModel;
import org.sam.swing.table.JSTableModelLinster;
import org.sam.swing.table.JTableModel;
import org.sam.swing.table.TableModelStateChangeListener;
import org.sam.swing.table.defaultImpl.JSTableModelDefaultAdapter;
import org.sam.swing.table.verification.VerificatEventListener;
import org.sam.swing.table.verification.Verification;
import org.sam.swing.utils.ReflectUtil;

/**
 * 树形表格model
 * 
 * @author sam
 *
 * @param <P>
 *            父节点类型
 * @param <C>
 *            子节点类型
 */
public class JSTreeTableModel<P, C> extends AbstractTreeTableModel
		implements JTableModel<Collection<P>>, TreeModelListener {

	/**
	 * 原始的值
	 */
	private volatile Collection<P> orginal;

	/**
	 * 删除的对象集合o
	 */
	private Collection<P> deletes = new LinkedList<>();

	/**
	 * 要更新的集合列表
	 */
	private Collection<P> modifies = new LinkedList<>();

	/**
	 * 需要创建的对象列表
	 */
	private Collection<P> creates = new LinkedList<>();

	/**
	 * 当前的父类的类型
	 */
	private Class<P> parentCls;

	/**
	 * 当前的子类类型
	 */
	private Class<C> childCls;

	/**
	 * 父类子类绑定字段
	 */
	private String field;

	/**
	 * 显示列的集合
	 */
	protected List<JSTableTreeTableColumn> columnIdentifiers = Collections.synchronizedList(new LinkedList<>());

	/**
	 * 注入的tablemodel对象
	 */
	private JSTableModelLinster<Collection<P>> tableModelLinster;

	/**
	 * 表格变化事件通知对象
	 */
	private List<TableModelStateChangeListener> stateChangeListeners = new LinkedList<>();

	/**
	 * 保护起来的单元格 存储格式为，行，列
	 */
	private Map<Integer, Set<Integer>> protectCell = new LinkedHashMap<Integer, Set<Integer>>();

	/**
	 * 父类型
	 * 
	 * @return
	 */
	public Class<P> getParentCls() {
		return parentCls;
	}

	/**
	 * 父类型
	 * 
	 * @param parentCls
	 */
	private void setParentCls(Class<P> parentCls) {
		this.parentCls = parentCls;
	}

	/**
	 * 子类型
	 * 
	 * @return
	 */
	public Class<C> getChildCls() {
		return childCls;
	}

	/**
	 * 子类型
	 * 
	 * @param childCls
	 */
	private void setChildCls(Class<C> childCls) {
		this.childCls = childCls;
	}

	/**
	 * 父类，子类关系绑定字段
	 * 
	 * @return
	 */
	public String getField() {
		return field;
	}

	/**
	 * 父类，子类关系绑定字段
	 * 
	 * @param field
	 */
	private void setField(String field) {
		this.field = field;
	}

	/**
	 * 树形表格model
	 * 
	 * @param root
	 *            跟节点
	 * @param parentCls
	 *            父类型
	 * @param childCls
	 *            子类型
	 * @param field
	 *            绑定字段
	 */
	public JSTreeTableModel(Object root, Class<P> parentCls, Class<C> childCls, String field) {
		super(root);
		this.setParentCls(parentCls);
		this.setChildCls(childCls);
		this.setField(field);
	}

	// begin treetable

	/**
	 * Replaces the column identifiers in the model. If the number of
	 * <code>newIdentifier</code>s is greater than the current number of
	 * columns, new columns are added to the end of each row in the model. If
	 * the number of <code>newIdentifier</code>s is less than the current number
	 * of columns, all the extra columns at the end of a row are discarded.
	 * <p>
	 * 
	 * @param columnIdentifiers
	 *            vector of column identifiers. If <code>null</code>, set the
	 *            model to zero columns
	 */
	// from DefaultTableModel
	public void setColumnIdentifiers(List<JSTableTreeTableColumn> columnIdentifiers) {
		this.columnIdentifiers.clear();
		this.columnIdentifiers.addAll(columnIdentifiers);
		modelSupport.fireNewRoot();
	}

	/**
	 * {@inheritDoc} 如果用户设置了列类型，则直接取，否则从默认值取，默认值没有，则返回Object.class
	 */
	@Override
	public Class<?> getColumnClass(int column) {
		if (column < 0 || column > this.getColumnCount())
			return Object.class;

		JSTableTreeTableColumn col = this.columnIdentifiers.get(column);
		Class<?> colCls = col.getColCls();
		if (colCls != null)
			return colCls;

		if (col.getDefaultValue() != null) {
			return col.getDefaultValue().getClass();
		}

		return super.getColumnClass(column);
	}

	/**
	 * 获取列名称
	 */
	@Override
	public String getColumnName(int column) {
		if (column < 0 || column > this.getColumnCount())
			return super.getColumnName(column);

		JSTableTreeTableColumn col = this.columnIdentifiers.get(column);
		if (!StringUtils.isEmpty(col.getTitle())) {
			return col.getTitle();
		}

		if (!Objects.isNull(col.getHeaderValue())) {
			return col.getHeaderValue().toString();
		}

		return super.getColumnName(column);
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @author sam 类是否可以编辑，使用JSTableModel里的设置
	 */
	@Override
	public boolean isCellEditable(Object node, int column) {
		if (column < 0 || column > this.getColumnCount())
			return false;

		if (!this.getEditable())
			return false;

		JSTableTreeTableColumn col = this.columnIdentifiers.get(column);
		if (node.getClass().equals(childCls)) {
			return col.isVisible() && col.isEditable();
		} else if (node.getClass().equals(parentCls)) {
			return false;
		} else if (node.getClass().equals(root.getClass())) {
			return false;
		} else {
			return super.isCellEditable(node, column);
		}
	}

	/**
	 * {@inheritDoc} 判断是否是叶子节点
	 */
	@SuppressWarnings("unchecked")
	@Override
	public boolean isLeaf(Object node) {

		if (node.getClass().equals(childCls)) {
			return true;
		} else if (node.getClass().equals(parentCls)) {
			Method method = ReflectUtil.getMethod(node, this.getField());
			if (method != null) {
				Object invoke;
				try {
					invoke = method.invoke(node);
					if (invoke == null)
						return true;

					if (invoke instanceof Collection) {
						return (((Collection<C>) invoke).isEmpty());
					}
				} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
					e.printStackTrace();
				}
			}

		} else if (node.getClass().equals(root.getClass())) {
			return false;
		}

		return super.isLeaf(node);
	}

	/**
	 * 设置值，并且记录到系统里
	 */
	@Override
	public void setValueAt(Object value, Object node, int column) {
		super.setValueAt(value, node, column);
	}

	@Override
	public void valueForPathChanged(TreePath path, Object newValue) {
		// TODO Auto-generated method stub
		super.valueForPathChanged(path, newValue);
	}

	/**
	 * 总列数
	 */
	@Override
	public int getColumnCount() {
		return 0;
	}

	@Override
	public Object getValueAt(Object node, int column) {
		return null;
	}

	@Override
	public Object getChild(Object parent, int index) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public int getChildCount(Object parent) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public int getIndexOfChild(Object parent, Object child) {
		return 0;
	}

	// end

	// begin tabelMode

	@Override
	public Collection<P> getOrginal() {
		return null;
	}

	@Override
	public void setOrginal(Collection<P> orginal) {
		// TODO Auto-generated method stub

	}

	@Override
	public Collection<P> getDeletes() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void setDeletes(Collection<P> deletes) {
		// TODO Auto-generated method stub

	}

	@Override
	public Collection<P> getCreates() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void setCreates(Collection<P> creates) {
		// TODO Auto-generated method stub

	}

	@Override
	public Collection<P> getModified() {
		return null;
	}

	@Override
	public void setModified(Collection<P> modified) {

	}

	@Override
	public void resetUpdate() {

	}

	@Override
	public int onRetrieve() throws Exception {
		// try {
		//
		// orginal = this.getTableModelLinster().onRetrieve();
		// JSTableColumn[] cols = this.getTableColumns();
		//
		// if (orginal != null && !orginal.isEmpty()) {
		// for (Object entity : orginal) {
		// // 假设已经生成完成了列的映射，然后根据列绑定的次序我们插入数据
		// // 数据集合
		// Object[] datas = new Object[getColumnCount()];
		// for (int i = 0; i < getColumnCount(); i++) {
		// String colName = getColumnName(i);
		// if (JSTableColumn.COLUMN_ORIGINAL.equals(colName)) {
		// datas[i] = entity;
		// } else {
		// if (null == colName || colName.length() <= 0) {
		// datas[i] = cols[i].getDefaultValue();
		// } else {
		// Pair<Boolean, Object> result = ReflectUtil.invokeGetMethod(entity,
		// colName);
		//
		// if (result.getKey()) {
		// datas[i] = result.getValue();
		// } else {
		// Field field = this.getCls().getDeclaredField(colName);
		// if (field == null)
		// continue;
		// field.setAccessible(true);
		// datas[i] = field.get(entity);
		// }
		// }
		// }
		// }
		// addRow(datas);
		// }
		//
		// return orginal.size();
		// }
		//
		// } catch (Exception e) {
		// e.printStackTrace();
		// return -1;
		// }
		return 0;
	}

	@Override
	public boolean onDelete(int moduleRow) throws Exception {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean onInsert(int moduleRow) throws Exception {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean onAppend() throws Exception {
		// TODO Auto-generated method stub
		return false;
	}

	/**
	 * 
	 */
	@Override
	public JSTableTreeTableColumn[] getTableColumns() {
		return null;
	}

	@Override
	public boolean isQuickRetrieveModel() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void setQuickRetrieveModel(boolean quickRetrieveModel) {
		// TODO Auto-generated method stub

	}

	@Override
	public Boolean getEditable() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void setEditable(Boolean editable) {
		// TODO Auto-generated method stub

	}

	@Override
	public boolean isRetrieveWithEmptyRow() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void setRetrieveWithEmptyRow(boolean retrieveWithEmptyRow) {
		// TODO Auto-generated method stub

	}

	@Override
	public Map<Integer, Set<Integer>> getProtectCell() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void setProtectCell(Map<Integer, Set<Integer>> protectCell) {
		// TODO Auto-generated method stub

	}

	/**
	 * 数据操作适配对象
	 */
	@Override
	public JSTableModelLinster<Collection<P>> getTableModelLinster() {
		if (tableModelLinster == null)
			tableModelLinster = new JSTableModelDefaultAdapter<>();

		return tableModelLinster;
	}

	/**
	 * 数据操作适配对象
	 */
	@Override
	public void setTableModelLinster(JSTableModelLinster<Collection<P>> tableModelLinster) {
		this.tableModelLinster = tableModelLinster;
	}

	@Override
	public void addStateChangeListener(TableModelStateChangeListener l) {

	}

	@Override
	public void removeStateChangeListener(TableModelStateChangeListener l) {
		// TODO Auto-generated method stub

	}

	@Override
	public boolean isCellEditable(int row, int column) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean hasChange() {
		return false;
	}

	@Override
	public void moveRow(int srcRow, int tarRow) throws Exception {
		// TODO Auto-generated method stub

	}

	@Override
	public Collection<P> getDatas() throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void reBuildIndex(int colIndex, int begin, int seed) throws Exception {
		// TODO Auto-generated method stub

	}

	@Override
	public Object getData(int modelRow) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Object[] getCellData(int modelRow) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Object[] createNew() throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public int findIndexOf(Object data) throws Exception {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public void clear() throws Exception {
		// TODO Auto-generated method stub

	}

	@Override
	public void insert(int row, Object t) throws Exception {
		// TODO Auto-generated method stub

	}

	@Override
	public void replace(int row, Object t) throws Exception {
		// TODO Auto-generated method stub

	}

	@Override
	public void removeAll() throws Exception {
		// TODO Auto-generated method stub

	}

	@Override
	public void updateValueAt(Object aValue, int row, int column) throws Exception {
		// TODO Auto-generated method stub

	}

	@Override
	public Object[] getColData(int colIndex, int beginRow, int endRow) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean update() throws Exception {
		// TODO Auto-generated method stub
		return false;
	}

	/**
	 * 检索数据的操作
	 */
	@Override
	public int retrieve() throws Exception {
		return 0;
	}

	@Override
	public boolean delete(int modelRow) throws Exception {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean append() throws Exception {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean insert(int modelRow) throws Exception {
		// TODO Auto-generated method stub
		return false;
	}

	// end

	// begin treetable event

	@Override
	public void treeNodesChanged(TreeModelEvent e) {
		System.out.println("treeNodesChanged:");
		System.out.println(e);
	}

	@Override
	public void treeNodesInserted(TreeModelEvent e) {
		System.out.println("treeNodesInserted:");
		System.out.println(e);
	}

	@Override
	public void treeNodesRemoved(TreeModelEvent e) {
		System.out.println("treeNodesRemoved:");
		System.out.println(e);
	}

	@Override
	public void treeStructureChanged(TreeModelEvent e) {
		System.out.println("treeStructureChanged:");
		System.out.println(e);
	}

	@Override
	public org.sam.swing.table.JTableModel.RetrieveModel getRetrieveModel() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void setRetrieveModel(org.sam.swing.table.JTableModel.RetrieveModel model) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public boolean isUseClientVerification() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void setUseClientVerification(boolean used) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public Verification getVerification() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void setVerification(Verification verification) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public boolean isTableColumnVerificatior() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void setTableColumnVerificatior(boolean verificat) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void addVerificatEventListener(VerificatEventListener listener) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void removeVerificatEventListener(VerificatEventListener listener) {
		// TODO Auto-generated method stub
		
	}

	// end
}
